#include "mypthread.h"
#include <unistd.h>
#include <vector>
#include "BlockQueue.h"
#include "RingQueue.h"

int i = 0;

pthread_mutex_t out_mutex;

void Producers(RingQueue<int>& x)
{
    while(true)
    {
        x.push(i);
        pthread_mutex_lock(&out_mutex);
        std::cout << "Producers:" << i++ << std::endl;
        pthread_mutex_unlock(&out_mutex);
        sleep(2);
    }
} 

void Consumers(RingQueue<int>& x)
{
    while(true)
    {
        int front = 0;
        x.pop(front);
        pthread_mutex_lock(&out_mutex);
        std::cout << "Consumers:" << front << std::endl;
        pthread_mutex_unlock(&out_mutex);
    }
} 

template<class Fn, class T>
void CreateCom(std::vector<Thread<T>>& id, int num, Fn fn, T& data)
{
    while(num--)
    {
        id.emplace_back(fn, data);
        id.back().Start();
    }
}

template<class T>
void CreateProducers(std::vector<Thread<T>>& id, int num, T& data)
{
    CreateCom(id, num, Producers, data);
}

template<class T>
void CreateConsumers(std::vector<Thread<T>>& id, int num, T& data)
{
    CreateCom(id, num, Consumers, data);
}

template<class T>
void WaitAll(std::vector<Thread<T>>& id)
{
    for(int i = 0; i < id.size(); i++)
    {
        id[i].Join();
    }
}

int main()
{
    RingQueue<int>* rq = new RingQueue<int>(10);
    //BlockQueue<int>* bq = new BlockQueue<int>(10);
    std::vector<Thread<RingQueue<int>>> tid;
    CreateProducers(tid, 4, *rq);
    CreateConsumers(tid, 4, *rq);

    WaitAll(tid);
    return 0;
}


